next up previous

9.4.2 Message-handler Actions

The body of a message-handler is a sequence of expressions that are executed in order when the handler is called. The return value of the message-handler is the result of the evaluation of the last expression in the body.

Handler actions may directly manipulate slots of the active instance. Normally, slots can only be manipulated by sending the object slot-accessor messages (see sections 9.3.3.9 and 9.4.3). However, handlers are considered part of the encapsulation (see section 2.6.2) of an object, and thus can directly view and change the slots of the object. There are several functions which operate implicitly on the active instance (without the use of messages) and can only be called from within a message-handler. These functions are discussed in section 12.16.

A shorthand notation is provided for accessing slots of the active instance from within a message-handler.

Syntax

?self:<slot-name>

Example

CLIPS> (clear)
CLIPS>
(defclass A (is-a USER)
  (role concrete)
  (slot foo (default 1))
  (slot bar (default 2)))
CLIPS>
(defmessage-handler A print-all-slots ()
  (printout t ?self:foo " " ?self:bar crlf))
CLIPS> (make-instance a of A)
[a]
CLIPS> (send [a] print-all-slots)
1 2
CLIPS>

The bind function can also take advantage of this shorthand notation to set the value of a slot.

Syntax

(bind ?self:<slot-name> <value>*)

Example

CLIPS>
(defmessage-handler A set-foo (?value)
  (bind ?self:foo ?value))
CLIPS> (send [a] set-foo 34)
34
CLIPS>

Direct slot accesses are statically bound to the appropriate slot in the defclass when the message-handler is defined. Care must be taken when these direct slot accesses can be executed as the result of a message sent to an instance of a subclass of the class to which the message-handler is attached. If the subclass has redefined the slot, the direct slot access contained in the message-handler attached to the superclass will fail. That message-handler accesses the slot in the superclass, not the subclass.

Example

CLIPS> (clear)
CLIPS>
(defclass A (is-a USER)
  (slot foo (create-accessor read)))
CLIPS>
(defclass B (is-a A)
  (role concrete)
  (slot foo))
CLIPS> (make-instance b of B)
[b]
CLIPS> (send [b] get-foo)
[MSGPASS3] Static reference to slot foo of class A does not apply to [b] of B
[PRCCODE4] Execution halted during the actions of message-handler get-foo primary in class A
FALSE
CLIPS>

In order for direct slot accesses in a superclass message-handler to apply to new versions of the slot in subclasses, the dynamic-put and dynamic-get (see sections 12.16.4.10 and 12.16.4.11) must be used. However, the subclass slot must have public visibility for this to work (see section 9.3.3.8).

Example

CLIPS> (clear)
CLIPS>
(defclass A (is-a USER)
  (slot foo))
CLIPS>
(defmessage-handler A get-foo ()
  (dynamic-get foo))
CLIPS>
(defclass B (is-a A)
  (role concrete)
  (slot foo (visibility public)))
CLIPS> (make-instance b of B)
[b]
CLIPS> (send [b] get-foo)
nil
CLIPS>


next up previous