1. Summary
  2. Files
  3. Support
  4. Report Spam
  5. Create account
  6. Log in

Collecting Facts

Task

I want to collect references to facts in a multislot variable so I can process them later.

If you collect the facts and start the processing directly afterwards, ie there's no statements in between those two events that modify the Working Memory, then you can store the fact-indexes directly in the multislot.

However, facts are given new fact-indexes whenever modified. So in order to store references safely over a longer period of time you must have at least one slot, a unique identity, in the fact who's value won't change over time (think of it as a Primary Key in a Database table). This complicates the fact-retrieval somewhat but it can be made simpler using a deffunction that returns a fact-instance given an id.

Solution

Using these facts

CLIPS> (deftemplate person
  (slot id (default-dynamic (gensym)))
  (multislot name)
  (slot age))
CLIPS> (deffacts start
  (person (name Obi-Wan Kenobi) (age 57))
  (person (name Darth Maul) (age 54))
  (person (name Anakin Skywalker) (age 41))
  (person (name Han Solo) (age 29))
  (person (name Luke Skywalker) (age 19))
  (person (name Leia Organa) (age 19)))
CLIPS>

and this global variable and rule to collect all "Skywalkers" in Working Memory

CLIPS> (defglobal ?*skywalkers* = (create$))
CLIPS> (defrule collect-skywalkers
  (person (id ?id) (name $? Skywalker $?))
  =>
  (bind ?*skywalkers* (create$ ?*skywalkers* ?id)))
CLIPS> (reset)
CLIPS> (run)
CLIPS> ?*skywalkers*
(gen5 gen3)
CLIPS>

we end up with two facts in the global variable.

Since we're storing the symbolic links (the id slot) we also need a way to get the actual fact given an id

CLIPS> (deffunction get-person-fact-by-id (?id)
  (nth$ 1 (find-fact ((?fact person))
                     (eq ?fact:id ?id))))

Here's an example of using the function to print the name and age of the facts in the global variable

CLIPS> (progn$ (?id ?*skywalkers*)
  (printout t (implode$ (fact-slot-value (get-person-fact-by-id ?id) name)) " is "
              (fact-slot-value (get-person-fact-by-id ?id) age) " years old" crlf))
Luke Skywalker is 19 years old
Anakin Skywalker is 41 years old
CLIPS>