Jess Information

Jess Home
Jess 7 Features
Download Now!
Online Demo

Mailing List
Jess Wiki

More information Related Web Sites
User Contributions
JSR94 Info
Developer's Log
About This Site

JESS ®, the Rule Engine for the JavaTM Platform

Jess Wiki: Wrapper Facts


Wolfgang Laun
Wolfgang Laun a-t thalesgroup com

Name: Wrapper Facts

Intent: Envelop mutative facts to ensure constant reference values


An application needs to maintain a structure of facts using fact references, so that some slot value in one fact would be a reference to some other fact. Moreover, some of the facts in this structure have to be replaced dynamically by facts created from a different template. This can't be done with a call to update which would retain the original fact so that all references would remain valid. Instead, the obsolete fact has to be retracted and the new fact must be asserted. After this, however, all the reference to the old fact would be dangling pointer so that a lot of additional updates would be necessary.

The resulting design pattern is based on the introduction of "wrapper facts" that serve as steady points of reference and maintain the actual fact. Just three additional functions are required to handle wrapping, replacement and access to the wrapped fact.

Applicability: Complex fact structures (e.g., graphs).

Participants: None.

Sample code:

; A Wrapper template contains a single slot pointing to
; the actual fact. This could be changed arbitrarily; not
; only in its slot values due to a simple update but also
; its template may change, due to retract/assert.
(deftemplate Wrapper (slot ref))

; All asserted facts must be wrapped by calling wrap. Use
; the return value as a slot value linking other facts to
; this fact.
(deffunction wrap (?fact)
  (bind ?wrapper (assert (Wrapper (ref ?fact))))
  (modify ?fact (wrapper ?wrapper))
  (return ?wrapper)

; To retract and re-assert a wrapped fact, call replace
; with the newly asserted fact. It retracts the old
; wrapped fact and inserts it into the wrapper.
(deffunction replace (?wrapper ?fact)
  (retract ?wrapper.ref)
  (modify ?wrapper (ref ?fact))

; This is the additional dereferencing operation
; required to access the wrapped fact, given a pointer
; to its wrapper.
(deffunction deref (?w)
  (return ?w.ref)

Usage Example:

; Example.
; Text chunks are either represented as a String fact
; or as a Charseq fact, a single repeated character.
; Chunks are kept in a doubly linked list, with the
; pointer pointing to a Wrapper object.
; All wrapped facts have an additional slot pointing to
; its wrapper.
(deftemplate Links   (slot wrapper)(slot pred)(slot succ))
(deftemplate String  extends Links (slot str))
(deftemplate Charseq extends Links (slot char)(slot rep))


(bind ?s1 (wrap (assert (String (str "The quick brown fox")))))
(bind ?c1 (wrap (assert (Charseq (char " ")(rep 5)))))
(bind ?s2 (wrap (assert (String (str "jumps over the lazy dog")))))
(bind ?c2 (wrap (assert (Charseq (char "!")(rep 10)))))

; Modify the link slots.
(modify (deref ?s1) (succ ?c1))
(modify (deref ?c1) (pred ?s1)(succ ?s2))
(modify (deref ?s2) (pred ?c1)(succ ?c2))
(modify (deref ?c2) (pred ?s2))


; Utility function for the rule Expand.
(deffunction repeat (?c ?n)
  (bind ?str "")
  (while (> ?n 0) do
    (bind ?str (str-cat ?str ?c))
    (-- ?n))
  (return ?str)

; Replace a short Charseq by a String containing 
; the expanded character repetition.
(defrule Expand
  ?charseq <- (Charseq {rep <= 5))
  (bind ?str (repeat ?charseq.char ?charseq.rep))
  (printout t ?charseq.char "x" ?charseq.rep "=" ?str crlf)
  (replace ?charseq.wrapper
           (assert (String (pred ?charseq.pred)
                           (succ ?charseq.succ)(str ?str))))


Front Page | Sandbox | Recent Changes | Powered by Friki | Last Edited: 02 November 2008