To keep thing simple and see where it leads us we postulate here that a rule or a rule set is just a function of facts producing new facts. No more, no less.
Another "weaker" constraint of the design was to use
Datalog/Datascript Query to produce a "Result Set" from the "Input
Facts" and to generate the "Output Facts" from the "Result Set" in a
sufficiently flexible way. The mapcat
- aka flatMap
-style
concatenation of the "Output Facts" independently generated from each
row of the "Result Set" appeared then to be a natural choice.
Note that it does not always make sense to mix/conflate the input facts and the output facts, here illustrated by use of two different human languages:
(let [facts [[1 :is "odd"]
[2 :is "even"]]
rules (defrules
{:find [?number]
;; For each number produce this set of facts in
;; German:
:then [[?number :ist "gerade"]
[(inc ?number) :ist "ungerade"]
[(dec ?number) :ist "ungerade"]]
;; Restrict to even numbers from the set of English
;; facts by Datalog query:
:when [[?number :is "even"]]})]
(rules facts))
;; =>
#{[1 :ist "ungerade"]
[2 :ist "gerade"]
[3 :ist "ungerade"]})))
Still many rule engines insist on "inserting" deduced facts into the very database that was "queried".
Would such a calculus be useful or is it just mind gymnastics just to reinvent the wheel? Think of composable programs with "Rules" operating on "Sets of Facts". Think of N-ary Rules taking zero, one or more "Sets of Facts" as arguments and producing even more of that as a result:
Rules:: Facts1 -> Facts2 -> ... -> FactsN
Think of select ... from facts1 join facts2 ...
. Or is a join
rather bad analogy because it is too "cartesian"? What kind of
expressions besides function application should be allowed? In other
words, what are the built-ins? Some set operations like union and
diff? Joins? A plain irreversible union that trows facts of
different domains in a single pot/set is probably not a good idea
type-wise.
First you may consider bumping the version in
project.clj
. Remember that you cannot overwrite non-SNAPSHOT
versions and what gets published, stays public. You habe been warned!
With that said, here is the memo:
$ lein clean
$ lein jar
$ lein test
$ lein deploy clojars
The artifact goes to
f0becod/regelwerk repository
so the user name will be f0bec0d
. The passwort is one of the
Deploy Tokens generated at Clojars, likely stored in your KeePass.
Maybe an interesting read:
Copyright © 2022 Alexei Matveev alexei.matveev@gmail.com
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close