defmethods checking and returning values based on fact data

54 views
Skip to first unread message

Jose Antonio Escribano Ayllon

unread,
Apr 2, 2024, 2:33:30 PMApr 2
to CLIPSESG
Hi.

I am trying to make a function that should check for a couple of facts and return the value, but I can't make it work. Apparently there is not a structure that allows me to do this in CLIPS?

if should be something like this:
(defmethod (?entity_id)
      (or (entity_walk_speed_override ?entity_id ?walk_speed)
            (entity_walk_speed ?entity_id ?walk_speed)
     )
     (return ?walk_speed)
)

Is there any way to do this?

Cheers,
Jose

Ryan Johnston

unread,
Apr 2, 2024, 2:58:17 PMApr 2
to CLIPSESG
Hey, Jose

Refer to the basic programming guide section 2.3.2 Functions for how to use defmethod. You use `(or` in your example which leads me to believe you would best be served using something that selects facts and does something to each of them. Refer to section 12.9.12 Fact-set Queries and Distributed Actions for something a little closer to what you want.

CLIPS Support

unread,
Apr 2, 2024, 3:21:21 PMApr 2
to CLIPSESG
         CLIPS (6.4.1 4/8/23)
CLIPS>
(deftemplate entity_walk_speed_override
   (slot id)
   (slot speed))
CLIPS>
(deftemplate entity_walk_speed
   (slot id)
   (slot speed))
CLIPS>
(deffunction walk_speed (?entity_id)
   (do-for-fact ((?f entity_walk_speed_override))
                (eq ?f:id ?entity_id)
                (return ?f:speed))
   (do-for-fact ((?f entity_walk_speed))
                (eq ?f:id ?entity_id)
                (return ?f:speed))
   (return FALSE))
CLIPS> (walk_speed e1)
FALSE
CLIPS> (assert (entity_walk_speed (id e1) (speed 5)))
<Fact-1>
CLIPS> (walk_speed e1)
5
CLIPS> (assert (entity_walk_speed_override (id e1) (speed 6)))
<Fact-2>
CLIPS> (walk_speed e1)
6
CLIPS>

Jose Antonio Escribano Ayllon

unread,
Apr 3, 2024, 12:26:09 AMApr 3
to CLIPSESG
Thanks both for the reply.

I am still trying to understand how to formalize logic in the proper way. But I understand a bit better now.

Your solution seems to work, but I just noticed that the result doesn't vary if you call the deffunction twice in the same rule after a retract, let me put an example:

(defrule restore_original_speed
     (?f <- (entity_walk_speed_override ?entity_id ?speed_override))
=>
     (bind ?old_speed (walk_speed ?entity_id))
     (retract ?f)
     (bind ?new_speed (walk_speed ?entity_id))
)

Here in this context, I obtain both in ?old_speed and in ?new_speed the same value. I guess it is because the function value gets cached, but, is there a way to have like a "delayed decomposition" result?

Cheers,
Jose

Ryan Johnston

unread,
Apr 3, 2024, 8:58:39 AMApr 3
to CLIPSESG
Here is what I get when I attempt to use that code:

CLIPS> (defrule restore_original_speed

  (?f <- (entity_walk_speed_override ?entity_id ?speed_override))
  =>
  (bind ?old_speed (walk_speed ?entity_id))
  (retract ?f)
  (bind ?new_speed (walk_speed ?entity_id)))
[PRNTUTIL2] Syntax Error:  Check appropriate syntax for the first field of a pattern.

ERROR:
(defrule MAIN::restore_original_speed
   (?f

Note the error message at the end; the syntax of your rule antecedent is incorrect.

Can you try without wrapping the (?f <- (entity_walk_speed_override ?entity_id ?speed_override)) in parenthesis? Additionally, the code you used does not use the `deftemplate` as defined in Gary's code.

Here's what I got working.

CLIPS> (defrule restore_original_speed
  ?f <- (entity_walk_speed_override (id ?entity_id) (speed ?speed_override))

  =>
  (bind ?old_speed (walk_speed ?entity_id))
  (retract ?f)
  (bind ?new_speed (walk_speed ?entity_id))
  (println "?old_speec: " ?old_speed " ?new_speed: " ?new_speed))
CLIPS> (run)
?old_speec: 6 ?new_speed: 5

Jose Antonio Escribano Ayllon

unread,
Apr 9, 2024, 3:16:05 AMApr 9
to CLIPSESG
Thanks Ryan, 
I will keep investigating!
Reply all
Reply to author
Forward
0 new messages