Meikel  Brandmeyer avatar Meikel Brandmeyer committed 49c4938

Add generators and transform

Comments (0)

Files changed (1)

src/main/clojure/clojurecheck/core.clj

   bool
   (boolean 0.5))
 
-;; ## let-gen
+;; ## `let-gen` and `generators`
 ;;
 ;; `let-gen` was supposed to provide some domonad style interface
 ;; for easy building of custom generators. However this seriously
             `(SimpleValue. ~expr)
             (partition 2 (rseq bindings)))))))
 
+(declare transform)
+
+(defmacro generators
+  "Takes a map of locals to generators. Upon generation of a value, binds
+  the generated values to the locals and executes body to obtain the final
+  value. Binding happens in parallel—similar to `binding`.
+
+  Shrinking is handled by shrinking each generator one after the other
+  and executing the body with the shrunken values in place."
+  {:added "2.1"}
+  [bindings & body]
+  (let [ks  (keys bindings)
+        gen (zipmap (map (fn [k] `(quote ~k)) ks) (vals bindings))]
+    `(transform ~gen (fn [{:syms [~@ks]}] ~@body))))
+
+(defn transform
+  "Generates a value according to `gen` and calls `f` with the generated
+  value—not the domain value. The return value of `f` becomes the new
+  value.
+
+  Shrinking is handled by shrinking the original domain value and
+  mapping `f` over the resulting sequence of shrunken values."
+  {:added "2.1"}
+  [gen f]
+  (let [transformer (fn transformer [dval]
+                      (ShrinkableValue. (SimpleValue. (f (value dval)))
+                                        (fn [_]
+                                          (map transformer (shrink dval)))))]
+    (reify
+      Generator
+      (arbitrary [this size] (transformer (generate gen size))))))
+
 (defn frequency
   "Chooses one of the given generators based on the associated
   weights. The size guidance is passed verbatim to the chosen
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.