Hey Kenny, I did a lot of thinking about what you said about declarative vs. imperative. I'm not sure what's the right terminology, but I did finally see the light.
We've had problems in applications written in our framework when there are multiple producers of one datum. In a lot of cases (benign and simple), it's been OK. However, as soon as things get bigger, we put a repeating pattern into our designs where a single controller function will act as a gatekeeper, reading from multiple channels of data, and forming the single producer for the difficult datum in the previously intractable design.
I've thought about it quite a bit, and I've proved to myself that this is equivalent to your declarative model, even if there are some slight structural differences*. So, in order for me to get from where I am to where Cells is, all I need to do is instead of waiting for the multiple producers issue to get out of hand and uncontrollable...just nip it in the bud and don't allow it to begin with. Then every piece of data has only one producer.
Thanks again for talking with me about it!
Mike
* Speaking of structure, question for you. Let's say you're declaring a slot to be a function of a couple other slots in Cells. How do you know they exist? I.e., where do you find your objects? Do you have like a database somewhere (hash of name->object or the like) that you lookup to find things? Are they all passed in at construction time? (I would imagine this wouldn't scale well at all). Is there some other scoping mechanism?
I'm not sure if Cells has any builtin support for finding the other objects/slots that participate in Cells, or if you roll your own per application...but I'd love to hear about how you solve it when *you* write code.
Mike J. Bell wrote:
Hey Kenny, I did a lot of thinking about what you said about declarative vs. imperative. I'm not sure what's the right terminology, but I did finally see the light.
We've had problems in applications written in our framework when there are multiple producers of one datum. In a lot of cases (benign and simple), it's been OK. However, as soon as things get bigger, we put a repeating pattern into our designs where a single controller function will act as a gatekeeper,...
Yep. I even cite such things as "prior art" of Cells, or at least other ways to address the issue (and serve as an existence proof that this is a real problem for complex applications).
reading from multiple channels of data, and forming the single producer for the difficult datum in the previously intractable design.
I've thought about it quite a bit, and I've proved to myself that this is equivalent to your declarative model, even if there are some slight structural differences*. So, in order for me to get from where I am to where Cells is, all I need to do is instead of waiting for the multiple producers issue to get out of hand and uncontrollable...just nip it in the bud and don't allow it to begin with. Then every piece of data has only one producer.
Thanks again for talking with me about it!
Mike
- Speaking of structure, question for you. Let's say you're declaring
a slot to be a function of a couple other slots in Cells. How do you know they exist? I.e., where do you find your objects? Do you have like a database somewhere (hash of name->object or the like) that you lookup to find things? Are they all passed in at construction time? (I would imagine this wouldn't scale well at all). Is there some other scoping mechanism?
The Family class is an integral part of all my applications. i even have special handling for the kids slot (the other slot forming the DAG is fm-parent), though I wonder if the fixes in Cells II obviate the need for that. Anyway....
A suite of routines will search the Family tree of objects in various ways. One is by name (the md-name of a model object) and lately I have found myself searching more often by type "gimme the nearest Selector above me so I can find out if I am part of the current selection".
And I /have/ been tempted to do something with a hash table of md-names, but one can get a lot of duplicates on that and one is usually searching relative to oneself.
The nice thing about this is that it turns out that a given sought object need not exist when a rule requiring one of its cells fires. Cells would be Hell to program is that were the case. Instead, what happens is that the traversing finder function keeps sampling the kids slots of this Family instance and that. If the kids are a rule and we are dealing with a brand new tree of widgets, a lot of these rules will not yet have fired (to produce the actual kid instances). No problemo. Rules fire on demand, so the instances pop into existence JIT. If your declarative code specifies the kid being sought, it will get created JIT before the original rule seeking it completes execution.
I was amazed when I saw that work, btw, many moons ago.
I'm not sure if Cells has any builtin support for finding the other objects/slots that participate in Cells, or if you roll your own per application...but I'd love to hear about how you solve it when *you* write code.
Check out the def-c-output KIDS method. (It might be .KIDS.) and the TO-BE function.
You are right: nothing says some other way of managing an object namespace could not be used. (Well, I /do/ have to make sure that Cells internals do not really need to be giving KIDS special handling... that may even have been an optimization or something to make debugging simpler "get the model population into existence first rather than have JIT model creation kicked off during rule fires."
kt