Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@ertugrulcetin
Last active September 30, 2020 14:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ertugrulcetin/548cbfd7d19aec57d42e7a1a3e51cbb7 to your computer and use it in GitHub Desktop.
Save ertugrulcetin/548cbfd7d19aec57d42e7a1a3e51cbb7 to your computer and use it in GitHub Desktop.
Revealing variables final values based on substitution map by using logic programming in Clojure.
(require '[clojure.core.logic :refer [== run fresh]]
'[clojure.walk :as walk])
(defn function-call->form [form]
(walk/prewalk (fn [node]
(cond
(and (list? node)
(or (-> node first resolve nil?)
(-> node first resolve meta :special-form)
(-> node first resolve meta :macro)))
(cons 'list (cons `(quote ~(first node)) (rest node)))
(list? node)
(cons 'list node)
:else node))
form))
(defmacro reveal-bindings
"Reveals variables final values based on substitution map by using logic programming.
e.g.:
{A 2, B 3, C (+ A B)}
=> {A 2, B 3, C 5}"
[smap]
`(first (run 1 [v#]
(fresh [~@(keys smap)]
~@(for [[k v] smap]
`(== ~k ~(function-call->form v)))
(== v# (zipmap (keys '~smap) [~@(keys smap)]))))))
(defmacro eval-from-raw [smap code]
(let [bindings (mapcat identity (eval `(reveal-bindings ~smap)))]
`(let [~@bindings]
~code)))
(eval-from-raw {A 2, B 3, C (+ A B) D (+ A B C)} (println "Here is D: " D))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment