Hello!
I have the following class
(defmodel switch (component) ((pos :initarg :pos :initform (c-in :off) :accessor switch-position)))
and I've created lots of switches in a family and I can find them by name. Is there any elegant way of establishing a dependency between one particular instance of switches and some code? I mean, like a callback function to be called when the value of that switch changes?
If I use def-c-output on 'pos', it will get called whenever any of the switch instances sets it.
Thanks!
Here's what I'm currently doing (just an outline):
(defmodel switch (component) ((switch-position :cell t :initarg :switch-position :initform (c-in :off) :accessor switch-position) (change-handler :cell nil :initform nil :initarg :change-handler :reader switch-change-handler)))
(def-c-output switch-position (self new-value old-value) (when (switch-change-handler self) (funcall (switch-change-handler self) self new-value old-value)))
And then create instances:
... (mksys 'switch :main-battery-switch) (mksys 'switch :apu-start-switch :change-handler 'apu-start-switch-change-handler) ...
The reason I need the change handler is that the change handler has to modify the value of the self switch. For example, when apu-start-switch changes its value to :START, change handler schedules an action which will set the switch back to :ON after some time. I fail to see how I can do this using regular slot-dependency mechanisms provided by Cells.
Am I making any sense?
Hi -
Am 04.05.2007 um 22:41 schrieb Josip Gracin:
Here's what I'm currently doing (just an outline):
(defmodel switch (component) ((switch-position :cell t :initarg :switch-position :initform (c-in :off) :accessor switch-position) (change-handler :cell nil :initform nil :initarg :change-handler :reader switch-change-handler)))
(def-c-output switch-position (self new-value old-value) (when (switch-change-handler self) (funcall (switch-change-handler self) self new-value old-value)))
And then create instances:
... (mksys 'switch :main-battery-switch) (mksys 'switch :apu-start-switch :change-handler 'apu-start-switch-change-handler) ...
The reason I need the change handler is that the change handler has to modify the value of the self switch. For example, when apu- start-switch changes its value to :START, change handler schedules an action which will set the switch back to :ON after some time. I fail to see how I can do this using regular slot-dependency mechanisms provided by Cells.
Am I making any sense?
You do - yet there is another approach I adopted from Kenny:
-X-X-X-
(in-package :cells)
(defmodel component () ((.md-name :accessor id :initarg :id)))
(defmodel switch (component) ((value :accessor value :initform (c-in nil) :initarg :value)))
(defmodel apu-start-switch (switch) ((opcode :initform (c? (if (eql (^value) :START) :DO-START :DO-NOTHING)))) (:default-initargs :value (c-in :off)))
(defobserver opcode ((self apu-start-switch)) (when (eql new-value :DO-START) (format t "~&*** APU STARTING ...") (sleep 3) ;; Do something meaningful here ... (format t "~&*** ... APU STARTED - NOW SETTING APU SWITCH TO :ON") (with-integrity (:change self) ;; This is how you set the value (setf (^value) :ON)))) ;; while maintaining Cells rules for integrity
(defun run-test () (let ((apu-start-switch (make-instance 'apu-start-switch :id :apu-start-switch))) (format t "~&*** APU START SWITCH "~A" created." (id apu-start-switch)) (sleep 1) (format t "~&*** Now starting APU !") (setf (value apu-start-switch) :START) (format t "~&*** APU START SWITCH is now in position "~A"." (value apu-start-switch))))
-X-X-X- (you may need to reformat the code to be able to read - use your favorate editor)
Instead of making different instances of just the class SWITCH I often subclass - as shown above for the APU-START-SWITCH. I then model behaviour by having "remote control facility" - the OPCODE. By assigning values to the opcode the corresponding observer (see DEFOBSERVER above) is a way of modeling state-transitions conviniently IMO.
Feedback from others ???
HTH, Frank
Frank Goenninger wrote:
You do - yet there is another approach I adopted from Kenny:
Thanks! Now I have to spend some time examining stuff you've written that I've never heard of before (such as with-integrity...). :-) Also, there doesn't seem to be anything named "defobserver" in the latest asdf-installable cells. Has this become def-c-output perhaps?
Anyway, I was kind of trying to avoid sub-classing because I have lots of switches. I'll have to re-think that decision.
Am 06.05.2007 um 00:04 schrieb Josip Gracin:
Frank Goenninger wrote:
You do - yet there is another approach I adopted from Kenny:
Thanks! Now I have to spend some time examining stuff you've written that I've never heard of before (such as with- integrity...). :-)
Also, there doesn't seem to be anything named "defobserver" in the latest asdf-installable cells. Has this become def-c-output perhaps?
You definitely should get the CVS sources from common-lisp.net! See there for how to access the CVS repository... -
def-c-output (sort of) became defobserver ... Also, there's a big chance you won't find with-integrity in the asdf-installable sources...
Anyway, I was kind of trying to avoid sub-classing because I have lots of switches. I'll have to re-think that decision.
Yeah, it took some time for me too to take that decision. And it still is very situation/use case-dependent, so there's no "always go that route" rule available, IMO. Still, I don't mind heaving a few hundred classes defined in my Lisp programs (using AllegroCL 8 here).
Kenny is surprisingly quiet ... Maybe he's busy taking orders for his new AlgebraOne software ;-)
Cheers Frank
Frank Goenninger wrote:
You definitely should get the CVS sources from common-lisp.net! See there for how to access the CVS repository... -
I thought asdf-install was pretty much in sync with the CVS. Oh well...
OTOH, "check it out from CVS" is easier said than done, since none of the links to the CVS tree that I was able to find were valid. In the end I had to guess the correct location. Here it is, in case anyone is interested:
cvs -z3 -d:pserver:anonymous@common-lisp.net:/project/cells/cvsroot co cells