trouble with :fact-type-fn

42 views
Skip to first unread message

mathias....@gmail.com

unread,
Dec 22, 2020, 8:06:49 AM12/22/20
to Clara
Hi,

I was trying to use a custom fact-type-fn as explained in the docs, but I couldn't get it to work. I couldn't figure out what I was doing wrong, so I tried the example from the docs, like this:

(ns clara-test.core
  (:require [clara.rules :as clara :refer :all]
            [clara.tools.inspect :as inspect]))

(clara/clear-ns-productions!)

(defrecord IdHolder [id])

(defrule rule1
  [[IdHolder "A"]]
  =>
  (println "this should be printed"))

(-> (mk-session :fact-type-fn (fn [fact]
                                (cond
                                  (instance? IdHolder fact) [IdHolder (:id fact)]
                                  :else (type fact))))
    (insert (->IdHolder "A"))
    fire-rules)

(defrule rule2
  [IdHolder]
  =>
  (println "this actually is printed"))

(-> (mk-session)
    (insert (->IdHolder "A"))
    fire-rules)

The first one, using the custom fact-type-fn, does nothing, while the second print works fine (obviously). To me, it looks exactly like the example from the docs. Do I need something special in the insert maybe? Help would be very much appreciated!
I'm using clara version 0.21.0

thanks,
-Mathias

ethan.e....@gmail.com

unread,
Dec 22, 2020, 10:06:23 AM12/22/20
to Clara
Hey Mathias,

This is a bit of an oddity that I believe i have seen before. The issue seems to be with how clara resolves the fact type of the rule. Looking at the compiler code when generating the alpha nodes, if the fact-type is a symbol then it will be converted to a class otherwise it will remain as what ever was provided. This is to facilitate the default usage, ie. type as the default fact-type-fn

In the example you provided, this would mean that the fact type of rule1 would match on [`IdHolder "A"] and not [IdHolder "A"], the former being a vector composed of a symbol/string combo and the latter being a class/string combo.

Im a bit torn here on what should be expected of clara in this situation, I feel its not very transparent that in one case the symbol would be replaced by a class but on the other hand it might be dangerous for clara to try and traverse the fact-type and replace symbols.

All of that being said, to answer the question, to get the example to function as expected:
```
(fn [fact]
  (cond
    (instance? IdHolder fact) [IdHolder (:id fact)]
    :else (type fact)))
```
would simply need updated to:
```

(fn [fact]
  (cond
    (instance? IdHolder fact) [`IdHolder (:id fact)]
    :else (type fact)))
```

Hope this helps,
Ethan

mathias....@gmail.com

unread,
Dec 22, 2020, 10:37:17 AM12/22/20
to Clara
Thanks a lot for the fast reponse, Ethan!
Yes, that makes sense and should get me back on track. Probably I won't be the last one to look at http://www.clara-rules.org/docs/fact_type_fn_perf/ to try and speed things up, so maybe that example should be updated as well. I'll create a pull request on the clara-site repo.

thanks again!
-Mathias

Op dinsdag 22 december 2020 om 16:06:23 UTC+1 schreef ethan.e....@gmail.com:
Reply all
Reply to author
Forward
0 new messages