Skip to content

Instantly share code, notes, and snippets.

@jonase
Created March 26, 2012 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jonase/2205346 to your computer and use it in GitHub Desktop.
Save jonase/2205346 to your computer and use it in GitHub Desktop.
A more advanced rule system?
(ns termite.core
(:refer-clojure :exclude [==])
(:use [clojure.core.logic]))
(def inc-rule
(let [x (lvar)]
[#(all (== % `(~'+ ~x 1))
;; It's easy to add pattern predicates
(pred x number?))
#(== % `(inc ~x))]))
(def interop-rule
(let [object (lvar)
method (lvar)
args (lvar)]
[#(== % (llist '. object method args))
;; The substitution part of the rule can contain
;; arbitrary computation.
#(project [method args]
(== % `(~(symbol (str "." method)) ~object ~@args)))]))
(defn simplify-one [expr rules]
(let [alt (run* [q]
(fresh [pat subst]
(membero [pat subst] rules)
(project [pat subst]
(all (pat expr)
(subst q)))))]
(if (empty? alt) expr (first alt))))
(def all-rules [interop-rule inc-rule])
(simplify-one '(+ 2 1) all-rules)
(simplify-one '(. obj toString a b c) all-rules)
;; Open question: Can simple rules such as
;;
;; (let [x (lvar)]
;; [#(== % `(< ~x 0))
;; #(== % `(neg? ~x))])
;;
;; be hidden behind some macro magic so we could keep the "nice"
;; syntax of
;;
;; [(< ?x 0) (neg? ?x)]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment