diff --git a/clojic/deps.edn b/clojic/deps.edn index 0457871..0997ae9 100644 --- a/clojic/deps.edn +++ b/clojic/deps.edn @@ -1,5 +1,6 @@ {:deps {org.clojure/clojure {:mvn/version "1.10.0-RC2"} org.clojure/core.logic {:mvn/version "0.8.11"} + zprint {:mvn/version "0.4.15"} clj-wrap-indent {:mvn/version "1.0.0"}} :aliases {:runprobs {:main-opts ["-m" "clojic.core"]}}} diff --git a/clojic/src/clojic/core.clj b/clojic/src/clojic/core.clj index 65598ab..afef553 100644 --- a/clojic/src/clojic/core.clj +++ b/clojic/src/clojic/core.clj @@ -10,10 +10,12 @@ fail firsto fresh + matche resto run run* - succeed]])) + succeed]] + [zprint.core :as zp])) (def my-solutions {"Something trivial" :something @@ -31,6 +33,7 @@ (defn run-solutions [] (let [stop (atom false) + failing-test (atom nil) probcount (atom 0)] (doseq [{:keys [title description tests] :as p} problems :let [s (get my-solutions title :notdone)] @@ -43,14 +46,17 @@ {'__ (list 'quote s)} t) evaluated (binding [*ns* (find-ns 'clojic.core)] (eval newcode)) - result (if (true? evaluated) "pass!!" "FAIL")] - (when (or (not result) - (= s :notdone)) - (reset! stop true) - (println (format "\nTesting %s\nwith __ set to '%s': %s" - t - s - result)))))))) + result (true? evaluated)] + (println (format "\nTesting\n%s" (zp/zprint-str t 45) s)) + (if-not (or (not result) + (= s :notdone)) + (println (format "\n__ == %s : PASS!" s)) + (do + (reset! stop true) + (reset! failing-test title) + (println (format "\nTesting with __ set to '%s': %s" + s (if result "pass!!" "FAIL")))))))) + [(if @stop :fail :pass) @failing-test])) (defn -main [& _] (run-solutions)) diff --git a/clojic/src/clojic/problems.clj b/clojic/src/clojic/problems.clj index 627e65e..2d435cc 100644 --- a/clojic/src/clojic/problems.clj +++ b/clojic/src/clojic/problems.clj @@ -1,19 +1,21 @@ (ns clojic.problems) (def problems - [{:title "Something trivial" + [;; The first two are just to get people started: + {:title "Something trivial" :description "Put :something here" - :tests '[[(= __ :something)]]} + :tests '[(= __ :something)]} {:title "Something else trivial" :description "Put '(1 2 3) here" - :tests '[[(= __ '(1 2 3))]]} + :tests '[(= __ '(1 2 3))]} + ;; Real core.logic tests start here. {:title "Failure" :description (str "The fail goal never succeeds. run* always " "returns a (possibly empty) list of values for q.") :tests '[(= __ (run* [q] fail))] :tags ["TRS"]} {:title "Success" - :description "The succeed goal always succeeds. " + :description "The succeed goal always succeeds; a succeeding value not bound to anything in particular is called a 'fresh' value, and is one of _0, _1, _2, ...." :tests '[(= __ (run* [q] succeed))] :tags ["TRS"]} {:title "Unification 1" @@ -119,7 +121,7 @@ :tags ["GF"]} {:title "Conde 2" :description "As always, unbound variables in each conde clause are - 'fresh'." + 'fresh'. Each clause starts the 'fresh count' anew for that conde branch." :tests '[(= __ (run* [a b c] (conde [(== a :foo) @@ -173,7 +175,7 @@ [succeed fail])))] :tags ["TRS"]} {:title "Conde 8" - :description "" + :description "Who's hungry for some soup?" :tests '[(= __ (run* [r] (fresh [x y] (conde @@ -236,15 +238,16 @@ (resto '(a c o r n) v) (firsto v r))))] :tags ["TRS"]} - {:title "Sequences 6" - :description "Try to write a relation that succeeds when its input - is a list. Note that strings are not considered - sequences by the core.logic unifier." - :tests '[(= '(_0) (run 1 [q] (__ [7 8 9]))) - (= () (run 1 [q] (__ 42))) - (= '([[:foo]]) (run 1 [q] (__ q) (== q [[:foo]]))) - (= '() (run 1 [q] (__ q) (== q "seventeen")))] - :tags ["GF"]} + ;; TODO: get this one to work too + ;; {:title "Sequences 6" + ;; :description "Try to write a relation that succeeds when its input + ;; is a list. Note that strings are not considered + ;; sequences by the core.logic unifier." + ;; :tests '[(= '(_0) (run 1 [q] (__ [7 8 9]))) + ;; (= () (run 1 [q] (__ 42))) + ;; (= '([[:foo]]) (run 1 [q] (__ q) (== q [[:foo]]))) + ;; (= '() (run 1 [q] (__ q) (== q "seventeen")))] + ;; :tags ["GF"]} {:title "Matche 1" :description "Matche is a pattern-matching goal that can largely replace tedious uses of fresh, firsto, resto,