This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-10-30
Channels
- # aleph (4)
- # announcements (5)
- # architecture (1)
- # aws (5)
- # babashka (12)
- # beginners (143)
- # chlorine-clover (4)
- # cider (16)
- # clj-kondo (44)
- # cljfx (26)
- # cljsrn (2)
- # clojure (34)
- # clojure-europe (28)
- # clojure-gamedev (1)
- # clojure-nl (3)
- # clojure-provo (2)
- # clojure-spec (6)
- # clojure-uk (17)
- # clojurescript (99)
- # code-reviews (6)
- # core-async (15)
- # cryogen (9)
- # cursive (14)
- # data-science (1)
- # datomic (16)
- # duct (1)
- # events (4)
- # exercism (1)
- # figwheel-main (3)
- # fulcro (3)
- # hugsql (7)
- # leiningen (4)
- # malli (15)
- # off-topic (13)
- # pathom (8)
- # re-frame (7)
- # reitit (35)
- # remote-jobs (1)
- # sci (10)
- # shadow-cljs (32)
- # sql (5)
- # tools-deps (102)
- # tree-sitter (3)
- # uncomplicate (7)
- # vim (40)
- # xtdb (8)
Good evening! I've written specs to validate a small math language with addition and multiplication. Now I want to generate values! But I'm hitting Stack Overflow. I assume that's because my specs/generators are mutually recursive. Any tips for writing mutually recursive spec generators that don't blow the stack? Code attached.
Idea: write generators as functions rather than directly on specs. Argument: recursion depth. Call generator functions from the spec.
Followed through on a generator namespace with recursion limit. That fixed my StackOverflow. Sample for add and multiply:
(defn add [depth]
(gen/fmap to-list
(gen/tuple (gen/return '+) (expression (dec depth)) (expression (dec depth)))))
(defn expression [depth]
(if-not (pos? depth)
(number)
(gen/one-of [(number)
(multiply depth)
(add depth)])))
Note: Tree depth can also be controlled probabilistically. Make it more probable to take the non-recursive path than the recursive path. Example from the docs:
(gen/frequency [[9 gen/small-integer] [1 (gen/return nil)]])
The probability of the non-recursive path would have to counterbalance the fanout for the recursive paths.From reading test.check source, I see that many generators accept a size parameter. I suspect that I could have used that instead of inventing my own depth.
Grasp now supports finding keywords using clojure specs while also preserving location metadata! https://github.com/borkdude/grasp#finding-keywords This should come in handy for finding re-frame events and subscriptions in CLJS apps. I also made a #grasp channel