Fork me on GitHub

I have a spec for a sorted set of positive integers in a wide range (say 0 to 1000000). I want those to be keys in a map. how do I spec/def that map? (I'm pretty new to clojure, so I hope I'm using the right terms here)


In the normal use-case, there will only be up to a few dozen keys in the map.


(Not sure if this is the right place to ask) When using clojure.spec with ClojureScript, is it able to figure out which keys are being used in order to minimize the build size ?

Alex Miller (Clojure team)13:08:39

@nha I don’t know, but I would guess not. @dnolen would know.


@nha Dead Code Elimination (DCE) is purely a Google Closure thing


still eliminating keys is hardly going to save you anything at all - so I wouldn’t be all that worried about it


keywords are subject to constant optimization, i.e. single allocation and global usage


this also aids DCE

Alex Miller (Clojure team)13:08:48

I think probably the question is whether the spec definition and registration for an unused key can be eliminated


It was unclear, yes that is what I meant.


ah ok not currently, since it’s stored dynamically in an atom


Ah I see. It may not be an intended use, I just spec'ed some server-side functions and would like to reuse some of these for validation/coercion on the client side.


@nha I don’t see what that has to do with your question


Well embedding the validation/coercions fns for my DB (for instance) is not something I would like to have on my frontend code.


so split those apart


we’re not going to automate any of that stuff for you


Ok separate namespaces then.


Get it, thanks for your quick answers 🙂


@alexmiller it partly does, but can spec ensure that each element in the set has one in the map, and the other way around?


@alexmiller maybe I should be using other data structures altogether. I'm learning closure while designing this thing.

Alex Miller (Clojure team)15:08:46

to create a spec that makes assertions about a set and a map together, you will either need to spec a data structure that combines them or if you are passing them both as args together, that spec could be on the fdef args of that function

Alex Miller (Clojure team)15:08:56

both are possible, I’m just not sure what you’re doing from the description


@alexmiller Thanks! Do you have an example of the combined data structure way of doing it? The guide explains how to combine structures with s/keys, but I didn't see how to assert anything about the combination.

Alex Miller (Clojure team)16:08:36

You're talking about both a map and a set so those would have to be combined into something else to talk about them together

Alex Miller (Clojure team)16:08:51

Or maybe I totally misunderstand what you mean

Alex Miller (Clojure team)16:08:14

You can combine arbitrary specs with s/and


@alexmiller I'll push some code and link you to it. one sec.


@alexmiller is the sorted set, and #L115 is the map. how do I spec that each element has a corresponding element in the other structure?

Alex Miller (Clojure team)17:08:33

That question only makes sense in some context where both are present

Alex Miller (Clojure team)17:08:41

Either both parts of the same data value or both args in a call to the same function


@alexmiller you mean, I need to define a data-structure (or function, but let's go with DS for now) that combines both, right?

Alex Miller (Clojure team)17:08:49

Where is the code that's going to use these things together? What does that need? It feels like you are doing things that are disconnected from the actual problem you are solving. Specs don't exist in a vacuum.


There is no code yet. I'm brainstorming on how to model my problem by writing specs for the needed data structures. I'm learning clojure at the same time. Am I going about this the wrong way?


I have a proof of concept working. now I want to add a ton of features, but I'm trying to do so in an organized way, that won't lead to too many re-writes.


I thought if I have the data-structures and the states of the FSM that will be the brain of the thing, the rest of the code will be relatively easy.


@alexmiller Does that make sense?


I'm manipulating audio on disk into repeating loops in RAM. The data-structure in question is supposed to represent where in the disk-file each part of the RAM loop came from. I thought I'd use a sorted set for the indexes in the loop where I switch to another part of the source file, so that when I want to replace part of the audio with something else, I can easily find out which nodes to replace. The map contains, for each section, the rest of the data needed to construct the actual audio (so IOW: where does the audio come from for this section, how do I crossfade it, etc). I hope I'm making myself clear.


@magnetophon: It may help to think about whether the "sorted set of indexes" is just an implementation detail of you algorithm or whether it’s an inherently important data structure in its own right?


In other words, do you derive the set from the main data structure "internally", just for that piece of work, or are you passing it around "externally" along with the main data structure?


If the answer is "internal", then I don’t think you need to spec it, although you may spec functions that get passed both the set and the main DS (per Alex’s comment about spec’ing via fdef).


If the answer is "external", then the best solution is to pass around a higher level DS that contains both the sorted set and the "main" DS as elements — and have the spec for that higher level DS (since then it can check that the set element is consistent with the other DS element).


Does that help?


@seancorfield thanks. Needed some time to process that. I think the sorted set is an implementation detail. I might not even need it at all.


I thought I'd need it for performance, but I think I won't: I will be adding and removing indexes regularly, and for deciding which ones to remove or update I'll have to look at the value of the indexes. In practice there will be at most a few hundred indexes, so It'll be quick enough to go over them.


@alexmiller and @seancorfield Many thanks for your time and insight!


I've got a variable length vector (some elements are required, some are optional). I'm using cat to create a spec to check it, which works well. But when I want to generate examples, cat generates lists. Is there a way spec a vector this way?


I can achieve what I want with with-gen, but I believe it requires that I always have two specs - one for the list, as defined with cat and then another to wrap the default generator

Alex Miller (Clojure team)20:08:10

Yeah, this is a common problem (regex syntax in vector) and a reasonable workaround

Alex Miller (Clojure team)20:08:30

We have talked about creating vcat for this particular case


@alexmiller Glad to know I'm not totally missing something 😄. Thanks for the help. vcat would be very useful in my application.


Can’t you just use coll-of with :into [] for that?


Ah, you’re talking about heterogeneous vectors, not homogeneous...

Alex Miller (Clojure team)21:08:44

Yeah. Comes up a lot in macro syntax.