I am aware of the member$
function in CLIPS. But its downside is that it only works on literal values as input. Does CLIPS have all/any/none functions where the elements are tested for a predicate? Something that would probably look like: (for-all <range-var> <source> <predicate>)
.
The problem I'm facing:
(deftemplate list (multislot vals))
(defrule first-high-val
(list
(vals
$?b ;; all of these should be less than or equal to 10
?x ;; first value to be greater than 10
$?e
) )
(test (for-all ?k $?b (<= ?k 10)))
=>
(println ?x)
)
Simply doing:
(defrule first-high-val
(list
(vals
$?b
?x & :(> ?x 10)
$?e
) )
=>
(println ?x)
)
is incorrect, because for (4 2 7 4 33 5 9 3 11 8 3 0)
the rule would have an activation for 33
and for 11
respectively, while 11
is not the first number to be greater than 10.
There's a foreach function which allows you to apply actions to every member of a list, but there's not a comparable function for seeing if every member satisfies a query. You can write a deffunction that will do the iteration and predicate test for you:
CLIPS> (deftemplate list (multislot vals))
CLIPS>
(deffunction for-every (?list ?op ?value)
(foreach ?item ?list
(if (not (funcall ?op ?item ?value)) then (return FALSE)))
(return TRUE))
CLIPS>
(defrule first-high-val
(list (vals $?b ?x&:(> ?x 10) $?e))
(test (for-every ?b <= 10))
=>
(println ?x))
CLIPS> (assert (list (vals 4 2 7 4 33 5 9 3 11 8 3 0)))
<Fact-1>
CLIPS> (run)
33
CLIPS>