Fork me on GitHub

@ddellacosta watch out - set-based specs dont work for false and nil

Oliver George04:02:52

Is anyone using caching/memoize type techniques to avoid instrumentation cost? Say keeping a cache of hash values for data which has been checked so that future checks are cheap.


@olivergeorge Given that instrument should be a dev/test-only activity, does performance matter?

Oliver George04:02:49

@seancorfield in this case it causes odd performance

Oliver George04:02:54

Laggy data input etc. In my case: checking the full definition of a complex form at each function/api call.


Well, yes, instrument has an overhead. Of course.

Oliver George04:02:22

Something you keep an eye out for when developing. Nice not to have false positives.


@seancorfield not if performance doesnt matter.

Oliver George04:02:05

Yeah. I appreciate that. Love spec. Caching would work. Just wondering if anyone has looked into using it.


If you have an implementation function and then a wrapper -- and the wrapper is memoized -- then instrumenting the implementation should only apply the overhead for each new set of arguments (and this seems the right way to deal with it).


I'd consider very slow/erratic behavior of an instrumented function to be a good indicator that I might need to cache/memoize the function anyway...?


(happy to be proved wrong but that's my initial intuition)

Oliver George05:02:01

Thanks. I see what you mean about wrapping a specific fn. That would do the trick for specific cases.

Oliver George05:02:54

@seancorfield any chance you know of a fifo memoize implementation for cljs?

Oliver George05:02:17

(worried that a long running SPA would gobble memory with memoize in the wrong place)


We can hope that core.cache and core.memoize get converted to .cljc perhaps?

Oliver George05:02:02

That does sound ideal.


(and we just got that functionality in the CI support for contrib projects so...)


As to your original Q, no, sorry, I've no idea about memoization for cls otherwise, sorry 😞


to support selective conforming (or protocol extensions) for the spec:


@not-raspberry I was looking for the equivalent of an enum of keywords, so think I’m safe here...

Oliver George21:02:21

@alexmiller I'm trying to understand if memoizing s/conform is likely to cause problems.

(set! s/conform (memoize (fn [spec x] (s/conform* (s/specize spec) x))))
Biggest risk I see is a spec changing causing the cached results to be invalid. Seems like the spec arg may vary in nature (keywords vs implementations). Perhaps it's better to memoize after calling (specize spec) ?

Alex Miller (Clojure team)22:02:21

same problems as usual with memoize:

Alex Miller (Clojure team)22:02:41

1) it’s an unbounded cache, which only fills up at 3 am in production


aw c’mon now, sometimes it fills up at 4am 😛

Alex Miller (Clojure team)22:02:21

2) you won’t see effects of any stateful changes (if in your repl, probably from changing specs). but if you made calls to anything stateful, you won’t see changes.

Alex Miller (Clojure team)22:02:31

@bbloom only on daylight savings change


good point.

Alex Miller (Clojure team)22:02:09

but specs are built with a delay anyways, which is forced on first use

Alex Miller (Clojure team)22:02:32

so they effectively already cache the spec conform implementation and won’t see changes if you change specs after use anyways

Alex Miller (Clojure team)22:02:52

so that’s maybe only a small downside


so I have a s/keys spec with :opt fields. When I use (gen/generate (s/gen ::my-spec) it generates them with :req fields and skips :opt fields. Is there a way to force :opt fields to be added?


if you generate a bunch of them it will add in optionals


generate starts out with the simplest possible values and gets more complicated as it goes


oh, wait, it actually does not skip :opt fields all the time, but now if I have (gen/vector (s/gen ::my-spec)) some items will have some of :opt fields and some would not. Is there a quick and easy way to fix that?


ag that’s what I meant above


if you want the field all the time, why are they optional?


because, in the runtime they are.


meh, I guess it’s actually fine.


I thought for a moment it’s just not generating :opt fields at all


I was wrong


you can use a custom generator if you want to add them all the time