; As always, I will post when the code is “complete”, but my progress can be followed on Github. Also, this post is executable, just copy and paste into a Clojure REPL.

(comment ” > Posts in this series: ch. 2, ch. 2 redux, ch. 3, ch. 4, ch. 5, ProloG pt. 1

First, let me thank Stuart Halloway for picking up the On Lisp -> Clojure port where I left off. I do not know if that was intentional, but in any case it makes for nice reading to start with my first 5 chapters and then transition right into Mr. Halloway’s posts (which are much higher quality IMO).

“)

; One of my favorite parts from On Lisp is his implementation of an embedded Prolog interpreter based on a simple database and inference system. My main goal for starting the On Lisp -> Clojure series was to eventually have this embedded Prolog system to use in my own applications. I will start out by just talking about a few preliminary structures and functions and then expand on them in future installments.

;

;;
;; The original Lisp make-hash-table function works on a 
;; cons-cell structure, however Clojure provides a persistent 
;; hash structure instead.  I am not going to port the Common 
;; Lisp function to Clojure, but instead will modify the Prolog 
;; implementation to fit a more idiomatic Clojure approach.
;; 
(defn make-db []
  nil)

(def *default-db* (ref (make-db)))

(defn clear-db 
  "Takes a db and clears it"
  ([] (clear-db *default-db*))
  ([db] (dosync (ref-set db nil))))

(defn db-query
  "Takes a db and a key and returns the mapped val"
  ([key] (db-query *default-db* key))
  ([db key] (get @db key)))

;;
;; db-push in Clojure is a bit trickier since it will be working
;; on a referenced persistent hash map.  This version is larger 
;; than the On Lisp version do to the fact that the database
;; being queried is an in-transaction value.  
;;
(defn db-push 
  "Stores a value in a the db"
  ([key val] (db-push *default-db* key val))
  ([db key val]
     (dosync
      (commute db
               (fn [the-db key val]
                 (assoc the-db key (cons val (get the-db key))))
               key
               val))))

;;
;; fact is almost a direct translation save for minor syntax diffs
;;
(defmacro fact 
  [pred & args]
  `(do
     (db-push '~pred '~args)
     '~args))

(defn test-pt1 []
  (fact painter reynolds joshua english)
  (fact painter canale antonio venetian)
  (db-query 'painter))

;

; There is definitely some room for improvement (suggestions/criticisms always welcome), but these initial functions work the same as the On Lisp originals, so that’s all for now. I’ll come back later for more.

;-m