Fork me on GitHub

Introducing Ghostwheel – it makes the writing, reading, refactoring, testing, instrumentation and stubbing of function specs easy; introduces a concise syntax for inline fspec definitions; helps keep track of side effects; and makes general debugging almost fun, with full evaluation tracing of function I/O, local bindings and all threading macros.

wizard 4

This looks really, really nice! I will for sure give it a try soon


Great, report back when you do!


how do i spec a function that has a variable number of arguments?


ah i think i see where my mistake is


i'm actually trying to spec a function that may have a variable number of arguments


so I should have an or


wonder if anyone can help me understand this


How would i write a spec such that all these conform?


(defn- zzz
  [i] i)

(defn- zzz-args
  [i args] i)

(defn- zzz-var-args
  [i & args] i)

(s/conform ::helpers/test zzz)
(s/conform ::helpers/test zzz-args)
(s/conform ::helpers/test zzz-var-args)


I've tried

(s/def ::helpers/test
  (s/fspec :args (s/or :a (s/cat :itineraries (s/coll-of string?)
                                 :args (s/* any?))
                       :b (s/cat :itineraries (s/coll-of string?)
                                 :args any?)
                       :c (s/cat :itineraries (s/coll-of string?)))))


but only (s/conform ::helpers/test zzz-var-args) conforms


They can't all conform: these are incompatible function signatures


you can write a spec such that the args for any of those signatures passes, but you can't disambiguate their meaning


nor can you work backwards: generated sample args from this spec won't work for all functions. zzz only works with :c and some :a for example


if you give it something matching :b it will fail

justinlee15:06:25 whew! you’ve been busy! i’ve just switched over to using spec-tools for its data-spec features that allow me to specify nested data types using data. I was going to try to get orchestra installed too so I can use their defn-spec, but your library looks like it provides that functionality and more. I think can can mix and match spec-tools with either of these. any pitfalls you can think of?


@lee.justin.m I honestly don't know. I have no experience with spec-tools and it is my (very superficial) understanding that they rely on some internal spec workings/APIs which are likely to change and break as spec matures and moves out of alpha, I remember reading a comment from Alex Miller to that effect, if I'm not mistaken. That's one of the reasons it hasn't been near the top of my list of new stuff to check out. Feel free to correct me if I'm mistaken and spreading FUD here, anyone. FWIW I can say that Ghostwheel is only using public APIs and not doing anything hacky at all. And if you do end up using it - feedback would be much appreciated! I've done a moderate amount of dogfooding, but there's always all kinds of things that tend to pop up in the wild.


Oh and btw, Ghostwheel also supports orchestra for instrumentation.

justinlee16:06:37 that’s true about spec-tools. it says so right in the readme. (doesn’t bother me though. code can always be changed 🙂 )


> code can always be changed tell that to python3


i’ve never kept up with python


and at any rate, spec tools is a small library. if they break it, i’ll just not upgrade or i’ll rewrite my types. it’s not mission critical


python3 was introduced in 2008. most of the community still uses python2 because they use libraries that are incompatible with version 3


oh. well that’s not exactly comparable. that’s changing out the whole language 🙂


if you are relying on the internals of spec, you need to change your code with updates to spec, and if you aren't careful your users need to change code too - the point here is the way that compatibility issues can fragment a community and get things stuck, and spec marks things as internal to avoid this kind of scenario


well spec should have given me a usable tool instead of cramming its way of doing things down my throat. by releasing this thing as an official library schema lost its mindshare so i’m kind of forced to use spec and i’m doing my best. i’m working on a product so there are no consumers of my code.


I basically just want to spec out the args inline using a macro. I think I’ll try yours out because maybe I can get tracing too. I never could get debux to work with shadow


Another thing that comes to mind regarding orchestra's defn-spec is that if I'm not mistaken it's not quite straightforward to do multi-arity functions with varying return specs between the different arities. With Ghostwheel it's just like writing single-arity functions and it automatically does the right thing.


And last but not least - migration to and from ghostwheel is easy, because you are not interspersing specs between the args, etc, you are basically just adding a single vector to the standard defn syntax


Regarding debux - I got it to work, sorta, and was considering using that, but I much prefer the clairvoyant+re-frame-tracer output, so I took those and pimped them a bit instead.

justinlee16:06:27 does all of this stuff print back to the repl? it seems like shadow-cljs defaults to the browser console. i’m just trying to figure out how it will work with all of this color output


It prints to the browser console, js/console.log basically.


There's also this nice little alternative to orchestra - I like that it's friendly to Cursive IDE syntax highlighting.


@metametadata So is Ghostwheel! Cursive-friendly that is.

👏 4