Created
October 8, 2017 00:56
-
-
Save taylorwood/232129ccd3cb809281fea591d46f1b8a to your computer and use it in GitHub Desktop.
Recursive clojure.spec for grouped/nested infix expressions http://taylorwood.github.io/2017/10/04/clojure-spec-boolean.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns playground.test | |
(:require [clojure.spec.alpha :as s] | |
[clojure.spec.gen.alpha :as sgen] | |
[clojure.spec.test.alpha :as stest] | |
[clojure.string :as cs] | |
[clojure.walk :as walk])) | |
(def op-keys #{:and :or}) | |
(s/def ::expression | |
(s/and keyword? | |
#(not (contains? op-keys %)))) | |
(s/def ::subgroup (s/or :g ::group :e ::expression)) | |
(s/def ::group | |
(s/cat :head ::subgroup | |
:tail (s/* (s/cat :op op-keys :clause ::subgroup)))) | |
(s/conform ::group [:x]) | |
(s/conform ::group [:x :y]) | |
(s/conform ::group [:x :and :y]) | |
(s/conform ::group [:x :and :y :or]) ;; hanging operator, no good | |
(s/conform ::group [:x :and :y :or :z]) | |
(s/conform ::group [:x :and :xx :and :yy :and [:y :or :z :or [:foo :and :bar]]]) | |
(s/conform ::group [[:x :or :y] :and :x]) | |
(s/conform ::group [[:x | |
:or :y | |
:or :z | |
:or [:q :and :z]] | |
:and :x | |
:and :y | |
:and :z | |
:and [:x | |
:or :y | |
:or :z | |
:or [:q :and :z]]]) | |
(sgen/sample (s/gen ::group)) | |
(defn clause-str [clause] | |
(walk/postwalk | |
(fn [elem] | |
(if (coll? elem) | |
(format "(%s)" (cs/join " " (map name elem))) | |
elem)) | |
clause)) | |
(s/fdef clause-str | |
:args (s/cat :clause (s/spec ::group)) ;; important to wrap regex spec in s/spec here | |
:ret string?) | |
(stest/instrument `clause-str) | |
(clause-str [[:x :or :y] :and :x]) | |
(map clause-str (sgen/sample (s/gen ::group))) | |
(binding [s/*recursion-limit* 1] ;; limit generative recursion, avoid long run time | |
(stest/check `clause-str)) | |
(stest/summarize-results *1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment