Hello,
Am I misunderstanding something, or should "model-object" in this error be replaced with "model"?
"If no superclass of X inherits directly or indirectly from model-object, model-object must be included as a direct super-class in the defmodel form for X"
Btw, cells seems very intuitive way to do GUI programming. I am new to both Lisp and GUI programming. The first thing I thought after getting mingled in some complicated callback hierarchies was that there must be a better way in Lisp to do this. And luckily I found cells. Thanks.
Best regards,
Mikko Ahonen
Mikko Ahonen wrote:
Hello,
Am I misunderstanding something, or should "model-object" in this error be replaced with "model"?
"If no superclass of X inherits directly or indirectly from model-object, model-object must be included as a direct super-class in the defmodel form for X"
My intention with the bifurcation of model-object and model is that model-object would have everything needed for Cells, while model has the stuff I normally use. But the idea was that if someone really wanted to go nuts with experimenting with variations on Cells, model-object would be the bare minimum needed for Cells itself. The other stuff is about the important business of managing a bunch of cells-driven objects, but one could do that in lotsa ways.
If you saw something in model absolutely necessary for Cells to work, I goofed. :)
Btw, cells seems very intuitive way to do GUI programming.
Yeah, I have been doing it for years and I still am amazed at how easy it is to build highly dynamic interfaces that really add value for the user. We really flipped over it when we stumbled on it by accident back in '95.
I am new to both Lisp and GUI programming. The first thing I thought after getting mingled in some complicated callback hierarchies was that there must be a better way in Lisp to do this. And luckily I found cells. Thanks.
Cool. Philip Eby also talks about callback madness as motivating his Cells clone, Trellis (a Python project). I never thought about it as a callback thing, but it seems to be a recurring theme. :)
cheers,
ken
On Wed, Jul 9, 2008 at 1:41 AM, Kenny Tilton kennytilton@optonline.net wrote:
Thanks for the quick reply,
If you saw something in model absolutely necessary for Cells to work, I
goofed. :)
My question was based on error message that indicated that model-object was not exported (or something) when I was trying to inherit from model-object.
I looked into doc/*.lisp, test-cells/* and also cello, and only found references to model, not model-object. I figured that perhaps model-object was some left-over from previous versions, or something.
This is what I got:
"Error during finalization of class #<STANDARD-CLASS X 2173E1B3>: Cannot compute the class precedence list of #<STANDARD-CLASS X 2173E1B3> because the following class is not finalized #<FORWARD-REFERENCED-CLASS MODEL-OBJECT 223FBB43>"
(this is LispWorks 5.1 on OS X if it makes any difference, and extending a GUI component)
Works fine with model, though.
Cool. Philip Eby also talks about callback madness as motivating his Cells
clone, Trellis (a Python project). I never thought about it as a callback thing, but it seems to be a recurring theme. :)
Not that I would know much about GUIs, but perhaps it depends on the model used in the GUI library. I am now experimenting with LispWorks CAPI.
For example this screen become a hassle immediately with callbacks, even if it is quite simple in principle:
User is editing two-level hierarchical data. Thus, parent objects have children. This view shows single parent. The form on the right is used to edit a single child. On the left I have preview of each child for this parent. The child previews are clickable, and select the object for editing. When I edit the data, the underlying model should obviously change. So should the preview, if corresponding fields change, as well as the title and some other parts of the view as well.
Best regards,
Mikko Ahonen
Mikko Ahonen wrote:
On Wed, Jul 9, 2008 at 1:41 AM, Kenny Tilton <kennytilton@optonline.net mailto:kennytilton@optonline.net> wrote:
Thanks for the quick reply,
If you saw something in model absolutely necessary for Cells to work, I goofed. :)
My question was based on error message that indicated that model-object was not exported (or something) when I was trying to inherit from model-object.
Oh, I am forever having to export things that should have been exported in the first place except I never actually do that (go through a library, think about what should and should not be exported, then do so). So, yeah, model-object should be exported.
In case it was not clear, please do not take any failure to export as a /definite/ sign that you have gone wrong. Mind you, Cells has been used so heavily and is so small that normally anything that should be exported is exported, but this design bit is where I thought "well, someone might want to do this differently, let's not lock anything in" and we just have not yet run into that someone. )
I looked into doc/*.lisp, test-cells/* and also cello, and only found references to model, not model-object. I figured that perhaps model-object was some left-over from previous versions, or something.
I understand. No, as I said "model" is my preferred way of managing an object-space if you will, and that is all my code (and some of Frank's) so it just looks as if model rules the Cells world.
This is what I got:
"Error during finalization of class #<STANDARD-CLASS X 2173E1B3>: Cannot compute the class precedence list of #<STANDARD-CLASS X 2173E1B3> because the following class is not finalized #<FORWARD-REFERENCED-CLASS MODEL-OBJECT 223FBB43>"
(this is LispWorks 5.1 on OS X if it makes any difference, and extending a GUI component)
Works fine with model, though.
Go with model, the family class and lots of other good stuff assumes that. You might be able to leverage some of that code.
Cool. Philip Eby also talks about callback madness as motivating his Cells clone, Trellis (a Python project). I never thought about it as a callback thing, but it seems to be a recurring theme. :)
Not that I would know much about GUIs, but perhaps it depends on the model used in the GUI library. I am now experimenting with LispWorks CAPI.
OK, that is the second explanation: with Cells we really have to build an abstraction that hides the callbacks, so in my GUI work the first three days are spent hiding the callbacks so I forget they are there. :)
If you look at Celtk or Cells-Gtk you'll see how I feed information from callbacks into the cells web so I can forget they are there. (Cello is just a wrapper for celtk.)
For example this screen become a hassle immediately with callbacks, even if it is quite simple in principle:
User is editing two-level hierarchical data. Thus, parent objects have children. This view shows single parent. The form on the right is used to edit a single child. On the left I have preview of each child for this parent. The child previews are clicAkable, and select the object for editing. When I edit the data, the underlying model should obviously change. So should the preview, if corresponding fields change, as well as the title and some other parts of the view as well.
ISTR Peter H. tackling something similar with Cells-GTk and having to extend the GTk wrapper to be more aware of such things.
You remind me of a recent mindfuck: I have this math application that has a cool wysiwyg math editor. Kids can be working on multi-problem assignments, but I show them only one at a time. A grid of little blank rectangles signifies the collection, and they click on any to call up that problem for work. I had already done textual tooltips, and it occurred to me that my gui was so cool I could just as easily make a hairy math expression into a tooltip. Now I knew they might need time to think so these tooltips do not go away after a few seconds as per standard. And a tooltip sure does not capture the edit focus. Omigod. Without writing a line of code I tried it: yep. If I moved the mouse over the icon for a problem and got the tooltip, I could then continue editing the problem and see both the problem and its tooltip change at the same time!
Not an important feature <g>, just an amazing manifestation of the power of the paradigm: a behavior like that /by accident/!
btw, if you are going to stick with CAPI the way to go is replicate the Celtk/Cells-Gtk/OpenAIR family of wrappers with sufficient glue to more or less make CAPI disappear. I am pretty busy these days, but I have an obscure interest in seeing that happen, and it is not all that hard, I'd be happy to help.
Otoh, Cells-Gtk or Celtk free you from a Lispworks lock-in (not that that is a bad thing).
kt
On Wed, Jul 9, 2008 at 4:04 AM, Kenny Tilton kennytilton@optonline.net wrote:
Go with model, the family class and lots of other good stuff assumes that. You might be able to leverage some of that code.
OK.
OK, that is the second explanation: with Cells we really have to build an abstraction that hides the callbacks, so in my GUI work the first three days are spent hiding the callbacks so I forget they are there. :)
I ended up writing some wrappers around CAPI already to simplify some setf-ery, so this is not a biggie. This way setf-every was not too bad, but when I extrapolated the work that needs to be done, the vision was callback hell.
If you look at Celtk or Cells-Gtk you'll see how I feed information from callbacks into the cells web so I can forget they are there. (Cello is just a wrapper for celtk.)
I'll look into them more deeply.
Not an important feature <g>, just an amazing manifestation of the power of the paradigm: a behavior like that /by accident/!
Sounds very cool. So far the biggest mind-fuck with my limited experience of cells is how it completely turns programming on its' head. Almost everything turns into dataflow, which seems to at least temporarily increase the number of cells.
The thought process is interesting. For example, I denote the selection of preview by flipping background and foreground colors. The parent container knows the selected child. In setf-ery, the (setf selected) method of the child would change the colors. First idea is to make each child have selected cell watching the selected cell of parent.
Then define observer on the selected of the child to actually change the colors. When I did that, I realized the need to ask for the colors from the parent, and setf them to local variables. Next, I noticed that hey, maybe foreground and background could be cells instead of local variables, and watching for the selected cell of the child. I ended up with one-line and 3 line observers for background and foreground, instead of single 15-line observer for the selected.
Now the next thought is that perhaps I could get rid of some of the intermediate cells, in this case the selected cell of the child. I guess when you turn programming on its' head, the dataflow becomes the "difficult part". My intuition says that at least to some point more intermediate cells makes dataflow more visible and reusable. So I kept the selected. But this may be because my background is in C shop where code readability was emphasized.
btw, if you are going to stick with CAPI the way to go is replicate the Celtk/Cells-Gtk/OpenAIR family of wrappers with sufficient glue to more or less make CAPI disappear. I am pretty busy these days, but I have an obscure interest in seeing that happen, and it is not all that hard, I'd be happy to help.
Otoh, Cells-Gtk or Celtk free you from a Lispworks lock-in (not that that is
a bad thing).
Great.
On this project I work with an user interface designer who is very visually oriented. Tk is a non-starter because the controls do not have a polished look. (Yeah, I know.). CAPI provides native GUI controls that are barely sufficient. But CAPI already limits us, however. For example, OS X Cocoa supports three sizes of controls, whereas CAPI has only one.
I also don't like vendor lock-ins. What I would prefer would be an open-sourced version of something like CAPI, and cells-CAPI to go along with it. I think splitting this into two different projects is better than single one, because you can get those cells skeptics involved, too. I think open source CAPI could be one of the biggest things missing from Lisp right now.
The first step into that direction would be to develop open source cells-CAPI. Perhaps it would also get more people interested in cells. I am ready to incrementally work towards something like this during this project, but of course, my deadline is impossible (like always).
Best regards,
Mikko Ahonen
Mikko Ahonen wrote:
On Wed, Jul 9, 2008 at 4:04 AM, Kenny Tilton <kennytilton@optonline.net mailto:kennytilton@optonline.net> wrote:
Go with model, the family class and lots of other good stuff assumes that. You might be able to leverage some of that code.
OK.
OK, that is the second explanation: with Cells we really have to build an abstraction that hides the callbacks, so in my GUI work the first three days are spent hiding the callbacks so I forget they are there. :)
I ended up writing some wrappers around CAPI already to simplify some setf-ery, so this is not a biggie. This way setf-every was not too bad, but when I extrapolated the work that needs to be done, the vision was callback hell.
Yes. Brooks identified this as the big problem with software development in general: an exponential explosion of complexity as the number and kinds of data points grows in ever larger applications, because these data points tend to be interdependent. Any one change must be propagated reliably to all the right other data points, in the right order. That is not only hard, it is also not fun, nice to have that managed automatically just as modern languages manage memeory automatically.
If you look at Celtk or Cells-Gtk you'll see how I feed information from callbacks into the cells web so I can forget they are there. (Cello is just a wrapper for celtk.)
I'll look into them more deeply.
Not an important feature <g>, just an amazing manifestation of the power of the paradigm: a behavior like that /by accident/!
Sounds very cool. So far the biggest mind-fuck with my limited experience of cells is how it completely turns programming on its' head. Almost everything turns into dataflow, ...
Yes, programming reverses direction. Instead of a programmer sitting there handling a state change figuring out how to push the change throughout the rest of the application, they just write standalone black-box rules and the Cells engine tkes any change and pulls the change thru the rest of the application.
And it is hard to do just a little dataflow, because once you start on this the cells is where the action is, so to see a change other things must be cells, too. The good news is that cells are more fun anyway, so it is OK that one gets forced into using cells everywhere. :)
which seems to at least
temporarily increase the number of cells.
I won't have time to write it up, but I inadvertently stress-tested Cells. My app got a little sluggish on some things when I had about five thousand instances and over eighty thousand Cells. I fixed my bug and got it down to a couple thousand instances and (IIRC) twenty thousand Cells and things are quite zippy. They absolutely screamed when I activated OpenGL display lists a couple of places, but then i got into some imaging bugs and I really do not have time to mess with OpenGL right now.
Anyway, I was surprised and made a mental note to stop thinking about Cells as expensive. They may even be faster: i did another benchmark to see how much work was being done on each change to ensure the Cells integrity and it was much less than I thought. I knew cells guaranteed that only rules that needed to run would run and that that would make things optimal, but what I also saw was that the integrity rules did not force Cells to visit almost every cell to see if it should run, as I had feared.
So i would wait for performance to become a problem. If/when it does, you can probably uses synaptic Cells to minimize recomputation, or perhaps the application will suggest a new cells trick -- recent work on a Cells-ODE had me implement user control over propagation so one could do a bunch of state changes and propagate just once. ie, where the user knows multiple state changes can safely be treated as one, they can now get that by wrapping them in with-user-propagation (or whatever I called it).
The thought process is interesting. For example, I denote the selection of preview by flipping background and foreground colors. The parent container knows the selected child. In setf-ery, the (setf selected) method of the child would change the colors. First idea is to make each child have selected cell watching the selected cell of parent.
Then define observer on the selected of the child to actually change the colors. When I did that, I realized the need to ask for the colors from the parent, and setf them to local variables. Next, I noticed that hey, maybe foreground and background could be cells instead of local variables, and watching for the selected cell of the child. I ended up with one-line and 3 line observers for background and foreground, instead of single 15-line observer for the selected.
Welcome to the club. Feels like a free lunch, eh? :)
Now the next thought is that perhaps I could get rid of some of the intermediate cells, in this case the selected cell of the child. I guess when you turn programming on its' head, the dataflow becomes the "difficult part". My intuition says that at least to some point more intermediate cells makes dataflow more visible and reusable. So I kept the selected. But this may be because my background is in C shop where code readability was emphasized.
btw, if you are going to stick with CAPI the way to go is replicate the Celtk/Cells-Gtk/OpenAIR family of wrappers with sufficient glue to more or less make CAPI disappear. I am pretty busy these days, but I have an obscure interest in seeing that happen, and it is not all that hard, I'd be happy to help. Otoh, Cells-Gtk or Celtk free you from a Lispworks lock-in (not that that is a bad thing).
Great.
On this project I work with an user interface designer who is very visually oriented. Tk is a non-starter because the controls do not have a polished look. (Yeah, I know.).
Do you know about the Tile package? I believe they are trying to be more native on the widgets. There is Tile support in Celtk, just not sure how robust it is -- I make all my own widgets using OpenGL.
Does your designer need "native", or do they just need "beautiful"? Perhaps they would get off on designing their own widgets.
CAPI provides native GUI controls that are barely sufficient. But CAPI already limits us, however. For example, OS X Cocoa supports three sizes of controls, whereas CAPI has only one.
I also don't like vendor lock-ins. What I would prefer would be an open-sourced version of something like CAPI, and cells-CAPI to go along with it. I think splitting this into two different projects is better than single one, because you can get those cells skeptics involved, too. I think open source CAPI could be one of the biggest things missing from Lisp right now.
The first step into that direction would be to develop open source cells-CAPI. Perhaps it would also get more people interested in cells.
I think that will require OpenAIR, the web 2.0 incarnation of cells.
As for getting more people interested: Cells picks up one new user every year, and it looks like you are the one for 2008 -- I have six months before I have to worry about finding another user.
I am ready to incrementally work towards something like this during this project, but of course, my deadline is impossible (like always).
Talk to your designer, and check out my beach rants on Google video. What I am sensing is that widget sets are terribly constraining when it comes to building fluent GUI experiences for users. Does your designer also have an interest in the user experience, as well as the visual quality? In cello I have core classes like view and control and then i just make up an interactive screen element as i need it, with whatever rendering and event handling I have in mind. Instead of forcing my design into the pigeonholes determined by a fixed widget set, I just follow the application and the GUI elements follow me. :)
cheers, ken
On Wed, Jul 09, 2008 at 09:38:25AM -0400, Kenny Tilton wrote:
As for getting more people interested: Cells picks up one new user every year, and it looks like you are the one for 2008 -- I have six months before I have to worry about finding another user.
:)
I am changing jobs soon, and I'm hopeful that I'll be able to build a good business case for using both CL and Cells. I use Lispworks, but I might have to "settle" for ECL or SBCL. We'll see.
I'm especially hopeful re: Cells because we're gonna be building v3 of an application that started life as an Excel spreadsheet.
-- L
Larry Clapp wrote:
On Wed, Jul 09, 2008 at 09:38:25AM -0400, Kenny Tilton wrote:
As for getting more people interested: Cells picks up one new user every year, and it looks like you are the one for 2008 -- I have six months before I have to worry about finding another user.
:)
I am changing jobs soon, and I'm hopeful that I'll be able to build a good business case for using both CL and Cells. I use Lispworks, but I might have to "settle" for ECL or SBCL. We'll see.
I'm especially hopeful re: Cells because we're gonna be building v3 of an application that started life as an Excel spreadsheet.
I remember someone mentioning that a big problem in tall buildings was the amount of business logic hidden in spreadsheets. I have this dream fantasy of getting rich just by writing a parser that would convert a spreadsheet to the equivalent Lisp/Cells application where they could see the rules anyway.
kt
So i would wait for performance to become a problem. If/when it does, you can probably uses synaptic Cells to minimize recomputation, or perhaps the application will suggest a new cells trick -- recent work on a Cells-ODE had me implement user control over propagation so one could do a bunch of state changes and propagate just once. ie, where the user knows multiple state changes can safely be treated as one, they can now get that by wrapping them in with-user-propagation (or whatever I called it).
Great. Luckily, the performance will probably not be a problem in this project.
Welcome to the club. Feels like a free lunch, eh? :)
Yes. when I saw Cells, I immediately also figured that if I had been more experienced, this kind of approach would have helped me with the nastiest programming challenge I have ever encountered: state management of database hot-standby feature. There, each instance is independent, but they must also keep track of each others (assumed) state. And there are both asynchronous and synchronous events coming in. Doing everything manually really sucked big time.
Do you know about the Tile package? I believe they are trying to be more native on the widgets. There is Tile support in Celtk, just not sure how robust it is -- I make all my own widgets using OpenGL.
I briefly looked at Tile. Looks like it could do the trick, but some stuff I get free.
Does your designer need "native", or do they just need "beautiful"? Perhaps they would get off on designing their own widgets.
The requirement is "beautiful". I just see "native" as the trade-off between effort and beautifulness which everybody can agree on for this version of the end-product. If the project succeeds we will go to self-designed widgets.
As for getting more people interested: Cells picks up one new user every
year, and it looks like you are the one for 2008 -- I have six months before I have to worry about finding another user.
:)
Talk to your designer, and check out my beach rants on Google video. What I
am sensing is that widget sets are terribly constraining when it comes to building fluent GUI experiences for users.
Heh, I checked the beach rants. The math learning application seemed really cool.
Does your designer also have an interest in the user experience, as well as the visual quality? In cello I have core classes like view and control and then i just make up an interactive screen element as i need it, with whatever rendering and event handling I have in mind. Instead of forcing my design into the pigeonholes determined by a fixed widget set, I just follow the application and the GUI elements follow me. :)
True, we are mostly interested in the user experience, eye-candy is secondary. Our needs are actually not very complicated, widget-wise. Drag and drop is the most complex feature we need. Otherwise, it is just data entry.
My approach is basically the same as yours. I created class for the preview etc. I just probably use little bit higher level widgets as building blocks. Minimally, clickable image with coordinate information is sufficient to create a buttons etc.
LispWorks seems to be perfect fit for this first project. Building the UI is really hassle-free, and end-result seems reasonably good.
I remember someone mentioning that a big problem in tall buildings was the
amount of
business logic hidden in spreadsheets. I have this dream fantasy of
getting rich just by writing
a parser that would convert a spreadsheet to the equivalent Lisp/Cells
application where they
could see the rules anyway.
If you want to become filthy rich, write a FileMaker to Lisp/Cells/Postgres converter with royalty-free deployment. Right now, each deployed application instance costs $$$. Application would actually be quite straightforward, as you can already copy-paste FileMaker views as XML. Of course, you would bankrupt billion-dollar business as a side-effect, so beware for the sunglassed men in black helicopters.
Best regards,
Mikko Ahonen
Mikko Ahonen wrote:
So i would wait for performance to become a problem. If/when it does, you can probably uses synaptic Cells to minimize recomputation, or perhaps the application will suggest a new cells trick -- recent work on a Cells-ODE had me implement user control over propagation so one could do a bunch of state changes and propagate just once. ie, where the user knows multiple state changes can safely be treated as one, they can now get that by wrapping them in with-user-propagation (or whatever I called it).
Great. Luckily, the performance will probably not be a problem in this project.
Kenny wrote:
Welcome to the club. Feels like a free lunch, eh? :)
Based on the past few days' experience allow me to qualify that. Cells has a cost, but it is a linear one: sorting out dependency screw-ups. Sometimes I create in one lexical block of code quite a deep structure, and if I happen not to wrap the initialization of a child in a rule and that initialization hits another cell (very likely) then the containing rule of that initialization (which wold have been the factory for that level of widgets!) ends up dependent on something it should not depeend on.
What is astonishing to me is that this normally works, even though it means that subtree of the GUI hierarchy was being forever re-instantiated! But I have become accustomed to being astonished this way, because it has happened from the beginning: things that should not work tend to go quite well 99% of the time.
In this case I had a classic foreign reference (my GUI "math keypad" looked at the Algebra being edited so it could offer little keys for the variables in use) and when some structure got pulled out from under it it ended up looking at dead instances. So I just fixed things so the foreign reference was in a rule and would stay current with the changing landscape.
One thing that is going on, btw, is improvements for Cells debugging, including in part me figuring out something I had missed about the ACL IDE. But re debugging, this brings me round to my main reason for responding.
At ECLM I was approached after my talk by an engineer from Lispworks. He astutely guessed that Cells presented challenges for debugging. I confirmed that one direction of improvement for Cells would be enhance diagnostics and debugging. But that was not the point I was getting at.
I ended up playfully suggesting CAPI get a Cells layer, hoping to land a project to do so. The engineer scoffed at the idea, saying there would have to be a lot of value in it for their customers before they would consider such a travesty, and he did not see any value. :) Since he already had seen Cells and how it worked, I suggested to him the problem might be that he is a compiler person, not an application developer. He actually assented to this, without budging.
So I have been enjoying greatly that the newest Cells fan is also a heavy CAPI user, and it was so easy for you to see the advantages.
I am reminded of the first folks shown Visialc. Most were programmers, one was a businessman. The programmers were bored by it, the businessman wanted to acquire the product. :)
Sounds like you are doing great with your new product. Good luck with it!
kt