Meikel  Brandmeyer avatar Meikel Brandmeyer committed 8ca977e

Deprecate let-gen

Comments (0)

Files changed (1)

src/main/clojure/clojurecheck/core.clj

   bool
   (boolean 0.5))
 
+;; ## let-gen
+;;
+;; `let-gen` was supposed to provide some domonad style interface
+;; for easy building of custom generators. However this seriously
+;; interferes with shrinking, since a generator might depend on its
+;; parameters on the random value of a previous generator. It is not
+;; clear how shrinking should work in this case.
+;;
+;; Hence, `let-gen` is deprecated in favor of `generators` which
+;; acts more like `binding` in that it binds things in parallel.
+(defmacro let-gen
+  "Takes a vector of let-like bindings. let-gen returns itself
+  a generator. When called it evaluates the generators on the
+  right hand side and assigns the result to the corresponding
+  local. Later generator definitions may refer to previous locals
+  as in a usual let.
+
+  Similar to for and doseq you can intersperse the bindings with
+  directives, which modify the behaviour.
+
+    * :when (pred? ...):
+      In case the predicate evaluates to false the generation
+      process is cancelled and retried.
+    * :let [...]:
+      Takes a normal let-style binding and makes the bindings
+      available to the following generator definitions."
+  {:added      "2.0"
+   :deprecated true}
+  [bindings expr]
+  (@#'clojure.core/assert-args
+       (vector? bindings)       "a vector for its bindings"
+       (even? (count bindings)) "an even number of forms in the bindings vector")
+  (let [size       (gensym "size__")
+        emit-g     (fn [[local gen] body]
+                     `(let [dval#  (generate ~gen ~size)
+                            ~local (value dval#)]
+                        ~body))
+        emit-p     (fn [pred body]
+                     `(when ~pred
+                        ~body))
+        emit-l     (fn [bindings body]
+                     `(let ~bindings
+                        ~body))]
+    `(reify
+       Generator
+       (arbitrary [this# ~size]
+         ~(reduce
+            (fn [body [v t :as bs]]
+              (case t
+                :when (emit-p v body)
+                :let  (emit-l v body)
+                (emit-g [t v] body)))
+            `(SimpleValue. ~expr)
+            (partition 2 (rseq bindings)))))))
+
 (defn frequency
   "Chooses one of the given generators based on the associated
   weights. The size guidance is passed verbatim to the chosen
         (when (pred (.value dom-value))
           dom-value)))))
 
-(deftype BoundDomain [generators values])
-
-(defmacro let-gen
-  "Takes a vector of let-like bindings. let-gen returns itself
-  a generator. When called it evaluates the generators on the
-  right hand side and assigns the result to the corresponding
-  local. Later generator definitions may refer to previous locals
-  as in a usual let.
-
-  Similar to for and doseq you can intersperse the bindings with
-  directives, which modify the behaviour.
-
-    * :when (pred? ...):
-      In case the predicate evaluates to false the generation
-      process is cancelled and retried.
-    * :let [...]:
-      Takes a normal let-style binding and makes the bindings
-      available to the following generator definitions."
-  {:added "2.0"}
-  [bindings expr]
-  (@#'clojure.core/assert-args let-gen
-       (vector? bindings)       "a vector for its bindings"
-       (even? (count bindings)) "an even number of forms in the bindings vector")
-  (let [size       (gensym "size__")
-        locals     (gensym "locals__")
-        generators (gensym "generators__")
-        values     (gensym "values__")
-        emit-g     (fn [[local gen] body]
-                     `(when-let [dval# (arbitrary ~gen ~size)]
-                        (let [~local      (.value dval#)
-                              ~generators (conj ~generators (.domain dval#))
-                              ~values     (conj ~values ~local)
-                              ~locals     (conj ~locals ~(keyword local))]
-                          ~body)))
-        emit-p     (fn [pred body]
-                     `(when ~pred
-                        ~body))
-        emit-l     (fn [bindings body]
-                     `(let ~bindings
-                        ~body))]
-    `(let [~locals     []
-           ~generators []
-           ~values     []]
-       (reify
-         Generator
-         (~'arbitrary
-           [this# ~size]
-             ~(reduce
-                (fn [body [v t :as bs]]
-                  (case t
-                    :when (emit-p v body)
-                    :let  (emit-l v body)
-                    (emit-g [t v] body)))
-                `(DomainValue. (BoundDomain. (zipmap ~locals ~generators)
-                                             (zipmap ~locals ~values))
-                               ~expr)
-                (partition 2 (rseq bindings))))))))
-
 (defn list
   "Generates a list based on the given generator. The length of
   the list is an integer generator. The default grows with the
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.