Kenny Tilton wrote:
If a new part is added or a part is deleted from the BOM or the price attribute is changed.
You just need slots Part-BOMs and BOM-Parts. Any rule such as:
(defclass BOM () () (:default-initargs :price (c? (apply '+ (mapcar 'price (^parts))))))
Will establish dependencies on (a) the parts slot and (b) the price of each part.
Nah, that will not work. We could have a parts slot on the BOM class mediated by c-input, but then how does each part get its BOMs slot updated? In the past I would kludge up an output method (via def-c-output) on the parts slot of BOM to maintain the BOMs slot of Part, but with Cells II we have a Prime Directive which says -- well, it gets complicated, but logically those two updates are one, and output methods do not run until propagation is complete, so the model is inconsistent during propagation of any change to the parts list of a BOM -- any rule that fires will see a BOMs value on any new part which does not show the BOM to which the part has been added.
We can go the RDBMS route and create or destroy instances of Relations, or we can do what AllegroStore does with its persistent CLOS database: define a so-called inverse function on a slot, via a new defmodel slot option. It would work like this:
(defclass BOM () ((parts :cell t :inverse-cell part-BOMs :initform (c-in nil) :initarg :parts :accessor parts)))
(defclass part ()())
After which:
(let ((p (make-be 'part)) (BOM (make-be 'bom :parts (c-in (list p))))) (part-BOMs p)) => A list containing the BOM instance
...and part-BOMS is a cell like any other cell, accept that there is no BOMs slot on part. Now Cells II's new propagation scheme naturally takes care of consistency, since it arranges for just-in-time consistency during propagation.
AllegroStore went one more step and supported a "unique" option for the case where a one-to-many relationship is to be modeled. We could then apply this to the Family class, where kids have only one fm-parent. What do we achieve by this? For one, the inverse Cell fm-parent will now return just one parent instance instead of a list of one. For another, an error can be generated if a kid gets pushed onto the kids slot of more than one instance at the same time.
This is interesting. Although I have gotten by nicely with the one Family class for a long time, I have started to notice occasions where the special handling given the kids slot might be useful more generally. I have even considered a new cell slot option which would let any slot work like the kids slot. We are talking about a different issue now, but it is interesting that they point back to the same kind of relational slot.
Thoughts?
kt