Releases: oakes/odoyle-rules
0.6.0
This release is all about recursion, and my never-ending attempts to tame that wild stallion. In particular, it builds on the existing {:then false}
feature, which is an option you can attach to tuples in your :what
block to prevent them from triggering the rule.
Firstly, it fixes a bug that prevented that feature from working with the new :then-finally
blocks. See the 0.5.0 release notes for an explanation of what those blocks are for.
Secondly, it extends this option so you can pass an arbitrary function to it, not just a boolean. The function takes two arguments: the new value from the tuple, and the old value it is replacing.
Why is that useful? It lets you say "this tuple should trigger the rule sometimes", rather than all the time or never. For example, {:then not=}
says that this tuple should only trigger the rule if the value in the tuple is not equal to the value it is replacing.
This seemingly small feature unlocks the ability to create recursive data structures as derived facts. We can now imitate the recursive queries of DataScript / Datomic! I wrote a longer explanation of this:
Using O'Doyle Rules as a poor man's DataScript
Thank you to Clojurists Together for supporting this release.
0.5.0
I love it when small changes have a big impact...that's called HIGH LEVERAGE, BABY! This release includes two such changes.
The first feature is about serialization. If you want to save your session or send it over a wire, you can now just call (query-all session)
, a new arity of the function, and it will return a vector of all the facts you inserted. Then just pr-str
it into an edn string (or your format of choice), and later on, parse and insert the facts into a new session. And then, as the Brits say, Bob's your uncle. I actually do have an uncle named Bob, BTW.
The second feature is a way to deal with collections of facts, much like Clara's accumulators. I had a realization that this doesn't need to be a special feature. We can just call query-all
inside a rule and insert the result as a new fact! Think of it as a "derived fact".
This was possible even before this release, but it had a flaw: Since :then
blocks only run after insertions, the derived fact would not update when facts were retracted. In this release, there is a new block type called :then-finally
, which runs after insertions and retractions. Take for example a to-do list:
(def rules
(o/ruleset
{::get-todo-item
[:what
[id ::text text]
[id ::done done]
:then-finally
(->> (o/query-all o/*session* ::get-todo-item)
(sort-by :id)
vec
(o/insert o/*session* ::derived ::all-todos)
o/reset!)}))
Here we are storing to-dos as individual facts, but our :then-finally
block creates a derived fact that contains all to-dos. When to-dos are added, updated, or removed, this derived fact will update as well. O'Doyle rules!
Thank you to Clojurists Together for supporting this release.