odoyle-rules icon indicating copy to clipboard operation
odoyle-rules copied to clipboard

What blocks then conditions don't allow for custom functions.

Open drewverlee opened this issue 2 years ago • 2 comments

Here is a failing test that should pass, but doesn't, that demonstrates the issue:

(deftest allow-for-custom-then-functions
  (let [falsy  (fn [new old] false)
        fired? (atom false)]
    (-> (reduce o/add-rule (o/->session)
                (o/ruleset
                  {::rule1
                   [:what
                    [pid ::foo foo {:then falsy}]
                    :then
                    (println "fired")
                    (reset! fired? true)]}))
        (o/insert 1 ::foo "")
        o/fire-rules)
    (is (= @fired? false))))

drewverlee avatar Apr 02 '24 02:04 drewverlee

maybe this is by design? Here is where i assume this is happening at a glance:

(if-let [[then-type then] (-> node :condition :opts :then)]
                                      (case then-type
                                        :bool (fn [session new-fact old-fact]
                                                then)
                                        :func (if-let [old-fact (:old-fact token)]
                                                (fn [session new-fact old-fact]
                                                  (then (:value new-fact) (:value old-fact)))
                                                (fn [session new-fact old-fact]
                                                  true)))
                                      (fn [session new-fact old-fact]
                                        true))

drewverlee avatar Apr 02 '24 02:04 drewverlee

yep, this seems to be by design. Or at least, as the code above illustrates it always fires the first time:

(deftest allow-for-custom-then-functions
  (let [falsy  (fn [new old] false)
        fired (atom 0)]
    (-> (reduce o/add-rule (o/->session)
                (o/ruleset
                  {::rule1
                   [:what
                    [pid ::foo foo {:then falsy}]
                    :then
                    (swap! fired inc)]}))
        (o/insert 1 ::foo "")
        (o/insert 1 ::foo "")
        (o/insert 1 ::foo "")
        o/fire-rules)
    (is (= 0 @fired))))

result:

FAIL in () (NO_SOURCE_FILE:1110)
expected: (= 0 (clojure.core/deref fired))
  actual: (not (= 0 1))

Is this clear in the docs? Does it have to be this way? It seems counter intuitive.

drewverlee avatar Apr 02 '24 02:04 drewverlee