Problem with initial value of a shared slot and put-<slot> before and after message handler

43 views
Skip to first unread message

fs

unread,
Sep 5, 2012, 9:44:07 AM9/5/12
to clip...@googlegroups.com
I try to implement a before and after message-handler for an abstract class which should read a value from a subclassed instance which will determine the action taken. The subclass is a concrete class which has a shared 'detal-type' slot, which has a default value.
Basically, the code looks like this:

(defclass MAIN::ROOT
(is-a USER)
(role abstract)
(slot amount (type NUMBER) (default 0)))

(defclass MAIN::A
(is-a ROOT)
(role concrete)
(slot detail-type (access read-only) (storage shared) (default the-a-type)))

(defmessage-handler MAIN::ROOT put-amount before (?value)
(bind ?old-value (send ?self get-amount))
(if (numberp ?old-value) then
(printout t "Subtract old amount from " (send ?self get-detail-type) " " ?old-value crlf)
else
(printout t "ROOT put-amount before ignored" crlf)))
(defmessage-handler MAIN::ROOT put-amount after (?value)
(bind ?new-value (send ?self get-amount))
(if (numberp ?new-value) then
(printout t "Add new amount to " (send ?self get-detail-type) " " ?new-value crlf)
else
(printout t "ROOT put-amount after ignored" crlf)))

(definstances MAIN::instances
([inst-1] of A (amount 25))
([inst-2] of A (amount 1000)))

This is the output:

CLIPS> (reset)
ROOT put-amount before ignored
Add new amount to nil 25
ROOT put-amount before ignored
Add new amount to the-a-type 1000

The problem is with the nil in the first Add new... line. The first time an instance is created, the default value isn't available yet in the put-amount after handler. The second time, all works fine. I was expecting the default value to be available in the put after handler!

Questions:
At what time is the default value assigned to a (shared) slot?
Is this a bug or do I miss something more fundamental?

I use a work-around by adding a void instance of class A which is ignored by the rest of the program, however I hate work-arounds.

Artem Novikov

unread,
Sep 6, 2012, 8:02:50 AM9/6/12
to clip...@googlegroups.com
I'm not sure, but the default value of an abstract class? May be a value specified in a derived class?

среда, 5 сентября 2012 г., 21:44:07 UTC+8 пользователь fs написал:

Artem Novikov

unread,
Sep 6, 2012, 11:34:01 AM9/6/12
to clip...@googlegroups.com
I not clear understand your architecture, but you may use something like this:

(defclass MAIN::ROOT

(is-a USER)

(role abstract)

(slot amount (type NUMBER) (default 0)))


(defclass MAIN::A

(is-a ROOT)

(role concrete)

(slot detail-type (storage shared)))


(defmessage-handler MAIN::A create before ()

(bind ?self:detail-type the-a-type)

(printout t "Constructor " crlf))


(defmessage-handler MAIN::ROOT put-amount before (?value)

(bind ?old-value (send ?self get-amount))

(if (numberp ?old-value) then

(printout t "Subtract old amount from " (send ?self get-detail-type) " " ?old-value crlf)

else

(printout t "ROOT put-amount before ignored" crlf)))

(defmessage-handler MAIN::ROOT put-amount after (?value)

(bind ?new-value (send ?self get-amount))

(if (numberp ?new-value) then

(printout t "Add new amount to " (send ?self get-detail-type) " " ?new-value crlf)

else

(printout t "ROOT put-amount after ignored" crlf)))


(definstances MAIN::instances

([inst-1] of A (amount 25))

([inst-2] of A (amount 1000)))


Constructor

ROOT put-amount before ignored

Add new amount to the-a-type 25

Constructor

ROOT put-amount before ignored

Add new amount to the-a-type 1000




четверг, 6 сентября 2012 г., 20:02:50 UTC+8 пользователь Artem Novikov написал:

fs

unread,
Sep 6, 2012, 1:37:53 PM9/6/12
to clip...@googlegroups.com
Thanks again.

I use the message handler MAIN::ROOT put-amount before to do some calculations depending on the type of subclass. I could of course use message handlers for each of subclasses, but that would require several copies of nearly the same code. I would have prefered using the default values for readibility, I was expecting the 'after' message-handlers to execute after the creation of the instance.
It does not seem to have to do anything with the abstract role of the ROOT class.
I guess using your solution is better than the work-around I was using.

Cheers

Artem Novikov

unread,
Sep 7, 2012, 8:22:46 AM9/7/12
to clip...@googlegroups.com
You may try play with MAIN::ROOT create before 

пятница, 7 сентября 2012 г., 1:37:53 UTC+8 пользователь fs написал:
Reply all
Reply to author
Forward
0 new messages