Liking cljdoc? Tell your friends :D

Rules:: Facts -> Facts'

Clojars Project

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.

Example Usage

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".

Next Level: Lamda Calculus with Sets of Facts

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.

Build & Deploy to Clojars

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.

Links

  • Maybe one shlould read PAIP before even attempting ...
  • See Datascript dialect of Datalog.
  • Minikusari in less two dosen lines of code generates transaction datoms (facts) from the result set of a Datascript query.
  • naga seems to be generating facts from rules.
  • Souffle Lang uses plain *.facts for input- and output relations.
  • Formulog delivers an executable JAR that transforms program "text" to fact database "text" bei executing Rules
  • Crepe DSL in Rust that Acknowledges Souffle & Datalog for inspiration.
  • Functional Production Rules
  • Another unifier-based query engine
  • Meander

Maybe an interesting read:

License

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