Search code examples
clips

Filtering on specific slot while retrieving multislot values


I'd like to retrieve a multislot containing object, and filter on a specific slot at the same time (fetching time). This is a code example:

(defclass OBJECT (is-a USER)
    (slot uuid
        (type STRING))
    (slot enable
        (type NUMBER)
        (allowed-integers 0 1) (default 0)))


(defclass GROUP (is-a USER)
    (slot uuid
        (type STRING))
    (multislot objects
        (type INSTANCE)))

(defrule my-rule  
    ?group <- (object (is-a GROUP) (uuid ?uuid) (objects $?objects&:(eq enable 1)))  ;; I want only enable rooms 
=>
(printout t "done" crlf))

Is it possible in CLIPS?

Thank you Nicola


Solution

  • You can filter the objects on the RHS of the rule:

    CLIPS> 
    (defclass OBJ
       (is-a USER)
       (slot uuid
          (type STRING))
       (slot enable
          (type NUMBER)
          (allowed-integers 0 1) 
          (default 0)))
    CLIPS> 
    (defclass GROUP (is-a USER)
       (slot uuid
          (type STRING))
       (multislot objects
          (type INSTANCE-NAME)))
    CLIPS> 
    (definstances initial
       ([o1] of OBJ (enable 1))
       ([o2] of OBJ (enable 0))
       ([o3] of OBJ (enable 1))
       ([o4] of OBJ (enable 0))
       ([g1] of GROUP (objects [o1] [o2] [o3] [o4])))
    CLIPS>    
    (deffunction filter (?objects ?slot ?value)
       (bind ?result (create$))
       (progn$ (?o ?objects)
          (if (eq (send ?o (sym-cat get- ?slot)) ?value)
             then
             (bind ?result (create$ ?result ?o))))
       ?result)
    CLIPS>    
    (defrule my-rule  
       ?group <- (object (is-a GROUP)
                         (uuid ?uuid)
                         (objects $?objects)) 
       =>
       (bind ?objects (filter ?objects enable 1))
       (printout t "Objects = " ?objects crlf))
    CLIPS> (reset)
    CLIPS> (run)
    Objects = ([o1] [o3])
    CLIPS>